package com.zaoniao.enstudy.domain.client;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.fastjson2.JSON;
import com.zaoniao.enstudy.domain.entity.FileImportData;
import com.zaoniao.enstudy.domain.entity.ZaoWord;
import com.zaoniao.enstudy.domain.entity.ZaoWordExample;
import com.zaoniao.enstudy.domain.repository.ZaoWordExampleRepository;
import com.zaoniao.enstudy.domain.repository.ZaoWordRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;

@Slf4j
public class FileImportDataListener implements ReadListener<FileImportData> {
    /**
     * 每隔100条存储数据库，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 100;
    /**
     * 单词表repository
     */
    private final ZaoWordRepository zaoWordRepository;
    /**
     * 单词例句表repository
     */
    private final ZaoWordExampleRepository zaoWordExampleRepository;

    /**
     * 缓存的数据
     */
    private List<FileImportData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    public FileImportDataListener(ZaoWordRepository zaoWordRepository,
                                  ZaoWordExampleRepository zaoWordExampleRepository) {
        this.zaoWordRepository = zaoWordRepository;
        this.zaoWordExampleRepository = zaoWordExampleRepository;
    }


    /**
     * @param fileImportData  -
     * @param analysisContext -
     */
    @Override
    public void invoke(FileImportData fileImportData, AnalysisContext analysisContext) {
        log.info("解析到一条数据:{}", JSON.toJSONString(fileImportData));
        cachedDataList.add(fileImportData);
        // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    /**
     * @param analysisContext -
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // 数据不能被 BATCH_COUNT 整除还需要再保存一次。
        if(!CollectionUtils.isEmpty(cachedDataList)){
            // 这里也要保存数据，确保最后遗留的数据也存储到数据库
            saveData();
            // 存储完成清理 list
            cachedDataList.clear();
        }
        log.info("所有数据解析完成！");
    }

    /**
     * 保存数据入库.
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveData() {
        // 解析 cachedDataList, 分别存储单词以及单词例句
        List<ZaoWord> zaoWords = FileImportData.Converter.INSTANCE.data2doList(cachedDataList);
        zaoWordRepository.batchInsert(zaoWords);

        List<ZaoWordExample> zaoWordsEgOne = FileImportData.Converter.INSTANCE.data2doList1(cachedDataList);
        List<ZaoWordExample> zaoWordsEgTwo = FileImportData.Converter2.INSTANCE2.data2doList2(cachedDataList);
        zaoWordsEgOne.addAll(zaoWordsEgTwo);
        zaoWordExampleRepository.batchInsert(zaoWordsEgOne);
    }
}
